package cn.ruanyun.backInterface.modules.fadada.serviceimpl;

import cn.hutool.json.JSONUtil;
import cn.ruanyun.backInterface.base.RuanyunBaseEntity;
import cn.ruanyun.backInterface.common.constant.CommonConstant;
import cn.ruanyun.backInterface.common.enums.SignCheckEnum;
import cn.ruanyun.backInterface.common.pay.common.alipay.AliPayUtilTool;
import cn.ruanyun.backInterface.common.utils.ResultUtil;
import cn.ruanyun.backInterface.common.vo.Result;
import cn.ruanyun.backInterface.modules.base.pojo.User;
import cn.ruanyun.backInterface.modules.base.service.mybatis.IUserService;
import cn.ruanyun.backInterface.modules.fadada.mapper.MyContractSigningCheckMapper;
import cn.ruanyun.backInterface.modules.fadada.pojo.MyContractSigning;
import cn.ruanyun.backInterface.modules.fadada.pojo.MyContractSigningCheck;
import cn.ruanyun.backInterface.modules.fadada.service.IMyContractSigningCheckService;
import cn.ruanyun.backInterface.modules.fadada.vo.MyContractSigningCheckVO;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fadada.sdk.client.FddClientBase;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import reactor.core.publisher.Mono;
import reactor.core.scheduler.Schedulers;
import cn.ruanyun.backInterface.common.utils.ToolUtil;
import cn.ruanyun.backInterface.common.utils.SecurityUtil;
import cn.ruanyun.backInterface.common.utils.ThreadPoolUtil;

import javax.servlet.http.HttpServletRequest;


/**
 * 我的合同签署审核接口实现
 * @author z
 */
@Slf4j
@Service
@Transactional
public class IMyContractSigningCheckServiceImpl extends ServiceImpl<MyContractSigningCheckMapper, MyContractSigningCheck> implements IMyContractSigningCheckService {

    @Autowired
    private SecurityUtil securityUtil;
    @Autowired
    private IUserService userService;

    @Override
    public void insertOrderUpdateMyContractSigningCheck(MyContractSigningCheck myContractSigningCheck) {

        if (ToolUtil.isEmpty(myContractSigningCheck.getCreateBy())) {

            myContractSigningCheck.setCreateBy(securityUtil.getCurrUser().getId());
        }else {

            myContractSigningCheck.setUpdateBy(securityUtil.getCurrUser().getId());
        }


        Mono.fromCompletionStage(CompletableFuture.runAsync(() -> this.saveOrUpdate(myContractSigningCheck)))
                .publishOn(Schedulers.fromExecutor(ThreadPoolUtil.getPool()))
                .toFuture().join();
    }

    @Override
    public Result<MyContractSigningCheck> getMyContractDetail() {

        return Optional.ofNullable(this.getOne(Wrappers.<MyContractSigningCheck>lambdaQuery()
        .eq(MyContractSigningCheck::getCreateBy, securityUtil.getCurrUser().getId())
        .orderByDesc(MyContractSigningCheck::getCreateTime)
        .last("limit 1")))
        .map(myContractSigningCheck -> new ResultUtil<MyContractSigningCheck>().setData(myContractSigningCheck, "获取我的合同审核信息"))
        .orElse(new ResultUtil<MyContractSigningCheck>().setErrorMsg(201, "暂无数据！"));
    }


    @Override
    public Result<Object> checkMyContractSigningCheck(Integer code, String checkReason, String id) {

        return Optional.ofNullable(this.getById(id)).map(myContractSigningCheckNew -> {

            if (code == 1) {

                myContractSigningCheckNew.setSignCheck(SignCheckEnum.PRE_PART_TWO_SIGN);
                myContractSigningCheckNew.setCheckReason(checkReason);
                this.updateById(myContractSigningCheckNew);
            }else {

                myContractSigningCheckNew.setSignCheck(SignCheckEnum.CHECK_FAIL);
                myContractSigningCheckNew.setCheckReason(checkReason);
                this.updateById(myContractSigningCheckNew);
            }

            return new ResultUtil<>().setSuccessMsg("审核成功！");

        }).orElse(new ResultUtil<>().setErrorMsg(202, "审核失败！"));
    }

    @Override
    public String fadadaPartyTwoNotify(HttpServletRequest request) throws Throwable {

        Map<String, String> params = AliPayUtilTool.toMap(request);
        log.info("法大大" + params);
        log.warn("法大大回调消息参数=\n" + JSONUtil.toJsonPrettyStr(params));

        JSONObject object = new JSONObject();
        try {

            //付款状态
            String resultCode = params.get("result_code");
            String resultDesc = params.get("result_desc");
            String contractId = params.get("contract_id");

            if ("3000".equals(resultCode)) {

                //插入待审核合同数据
                Optional.ofNullable(this.getOne(Wrappers.<MyContractSigningCheck>lambdaQuery()
                .eq(MyContractSigningCheck::getContractId, contractId)))
                        .ifPresent(myContractSigningCheck -> {

                            myContractSigningCheck.setSignCheck(SignCheckEnum.PER_PART_ONE_SIGN);
                            this.updateById(myContractSigningCheck);
                            log.info("修改审核状态成功！");
                        });

                object.put("return_code", "200");
                object.put("return_msg", "支付宝notify_url 验证成功 succcess");
            }else {

                System.out.println("notify_url 验证失败");
                object.put("return_code", "-1");
                object.put("return_msg", resultDesc);
            }
        }catch (Exception e) {

            throw e.getCause();
        }

        return object.toJSONString();
    }

    @Override
    public String fadadaOneNotify(HttpServletRequest request) throws Throwable {

        Map<String, String> params = AliPayUtilTool.toMap(request);
        log.warn("法大大回调消息参数=\n" + JSONUtil.toJsonPrettyStr(params));

        JSONObject object = new JSONObject();
        try {

            //付款状态
            String resultCode = params.get("result_code");
            String resultDesc = params.get("result_desc");
            String contractId = params.get("contract_id");

            if ("3000".equals(resultCode)) {

                //插入待审核合同数据
                Optional.ofNullable(this.getOne(Wrappers.<MyContractSigningCheck>lambdaQuery()
                        .eq(MyContractSigningCheck::getContractId, contractId)))
                        .ifPresent(myContractSigningCheck -> {

                            myContractSigningCheck.setSignCheck(SignCheckEnum.PRE_PART_SAVE);
                            this.updateById(myContractSigningCheck);
                            log.info("修改审核状态成功！");
                        });

                object.put("return_code", "200");
                object.put("return_msg", "支付宝notify_url 验证成功 succcess");
            }else {

                System.out.println("notify_url 验证失败");
                object.put("return_code", "-1");
                object.put("return_msg", resultDesc);
            }
        }catch (Exception e) {

            throw e.getCause();
        }

        return object.toJSONString();

    }

    @Override
    public Result<Object> contractFilling(String id) {

        return Optional.ofNullable(this.getById(id)).map(myContractSigningCheck -> {


            FddClientBase base = new FddClientBase(CommonConstant.F_APP_ID, CommonConstant.F_APP_SECRET, CommonConstant.F_VERSION, CommonConstant.F_HOST);

            String result = base.invokeContractFilling(myContractSigningCheck.getContractId());

            if ("1000".equals(JSONObject.parseObject(result).getString("code"))) {

                myContractSigningCheck.setSignCheck(SignCheckEnum.COMPLETE);
                this.updateById(myContractSigningCheck);

                return new ResultUtil<>().setSuccessMsg("归档成功！");
            }else {

                return new ResultUtil<>().setErrorMsg(JSONObject.parseObject(result).getInteger("code"), JSONObject.parseObject(result).getString("msg"));
            }

        }).orElse(new ResultUtil<>().setErrorMsg(203, "不存在当前合同数据"));
    }

    /***
     * 合同审核列表
     * @param myContractSigning
     * @return
     */
    @Override
    public List<MyContractSigningCheckVO> pcGetmyContractSigning(MyContractSigning myContractSigning) {

        List<MyContractSigningCheck> list = this.list(Wrappers.<MyContractSigningCheck>lambdaQuery()
                .orderByDesc(RuanyunBaseEntity::getCreateTime));

        List<MyContractSigningCheckVO> myContractSigningVOS = new ArrayList<>();
        list.forEach(MyContractSigningCheck1 -> {

            MyContractSigningCheckVO myContractSigningVO = new MyContractSigningCheckVO();
            ToolUtil.copyProperties(MyContractSigningCheck1,myContractSigningVO);

            Optional.ofNullable(userService.getById(myContractSigningVO.getCreateBy()))
                    .ifPresent(user1 -> {

                        myContractSigningVO.setCreateNmae(user1.getUsername());
                    });

            myContractSigningVOS.add(myContractSigningVO);
        });
        return myContractSigningVOS;
    }

}